package net.starwifi.duobao.auth;



import net.starwifi.duobao.entity.Operator;
import net.starwifi.duobao.oauth.Principal;
import net.starwifi.duobao.service.CaptchaService;
import net.starwifi.duobao.service.OperatorService;
import net.starwifi.duobao.service.SettingService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.List;

/**
 * 权限认证
 */
public class AuthenticationRealm extends AuthorizingRealm {

	@Autowired
	private CaptchaService captchaService;

	@Autowired
	private OperatorService operatorService;

	@Autowired
	private SettingService settingService;

	/**
	 * 获取认证信息
	 * 
	 * @param token
	 *            令牌
	 * @return 认证信息
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken token) {
		AuthenticationToken authenticationToken = (AuthenticationToken) token;
		String username = authenticationToken.getUsername();
		String password = new String(authenticationToken.getPassword());
		String captchaId = authenticationToken.getCaptchaId();
		String captcha = authenticationToken.getCaptcha();
		String ip = authenticationToken.getHost();
		if (!captchaService.isValid(null, captchaId, captcha)) {
			throw new UnsupportedTokenException();
		}
		if (username != null && password != null) {
			Operator operator = operatorService.findByUsername(username);
			if (operator == null) {
				throw new UnknownAccountException();
			}
			if (!operator.getIsEnabled()) {
				throw new DisabledAccountException();
			}
			if(operator.getIsLocked()){
				String lockTime= settingService.findByCode("loginFailureLockTime").getConfigValue();
				int loginFailureLockTime =Integer.parseInt(lockTime);
				if (loginFailureLockTime == 0) {
					throw new LockedAccountException();
				}
				Date lockedDate = operator.getLockedDate();
				Date unlockDate = DateUtils.addMinutes(lockedDate, loginFailureLockTime);
				if (new Date().after(unlockDate)) {
					operator.setLoginFailureCount(0);
					operator.setIsLocked(false);
					operator.setLockedDate(null);
					operatorService.update(operator);
				} else {
					throw new LockedAccountException();
				}
			}
			if (!DigestUtils.md5Hex(password+operator.getSalt()).equals(operator.getPassword())) {
				String settingFailureCount= settingService.findByCode("loginFailureCount").getConfigValue();
				int settingFailureCountInteger =Integer.parseInt(settingFailureCount);
				int loginFailureCount = operator.getLoginFailureCount() + 1;
				if (loginFailureCount >= settingFailureCountInteger) {
					operator.setIsLocked(true);
					operator.setLockedDate(new Date());
				}
				operator.setLoginFailureCount(loginFailureCount);
				operatorService.update(operator);
				throw new IncorrectCredentialsException();
			}
			operator.setLoginIp(ip);
			operator.setLoginDate(new Date());
			operator.setLoginFailureCount(0);
			operatorService.update(operator);
			return new SimpleAuthenticationInfo(new OperatorPrincipal(operator.getId(), username), password, getName());
		}
		throw new UnknownAccountException();
	}

	/**
	 * 获取授权信息
	 * 
	 * @param principals
	 *            principals
	 * @return 授权信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		Principal principal = (Principal) principals.fromRealm(getName()).iterator().next();
		if (principal != null) {
			List<String> authorities = operatorService.findAuthorities(principal.getId());
			if (authorities != null) {
				SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
				authorizationInfo.addStringPermissions(authorities);
				return authorizationInfo;
			}
		}
		return null;
	}

}